package com.errol.sync.sync.wrapper;

import com.renjia.supervise.service.log.LogService;
import com.renjia.supervise.service.sync.DataSyncService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 同步服务 wrapper 实例工厂类，所有包装类实例都通过该工厂类创建，以此来注入 spring bean
 * 注意 包装类实例不能注册为 spring bean
 *
 * @author zhang xiao bin
 * @version v1.0
 * @date 2021/08/16
 * @since v
 **/
@Component
public class DataSyncWrapperFactory {

    private final ApplicationContext applicationContext;
    private final ConcurrentMap<Class<?>, BlockingQueue<SmartDataSyncWrapper.SyncTask>> syncMissionCache;
    private final TaskExecutor taskExecutor;
    private final LogService logService;

    public DataSyncWrapperFactory(ApplicationContext applicationContext,
                                  @Qualifier(value = "taskExecutor") TaskExecutor taskExecutor,
                                  LogService logService) {
        this.applicationContext = applicationContext;
        this.syncMissionCache = new ConcurrentHashMap<>();
        this.taskExecutor = taskExecutor;
        this.logService = logService;
    }

    /**
     * 获取异步执行数据同步任务的包装类实例
     */
    public DataSyncService getAsyncDataSyncWrapper(DataSyncService source) {
        return new AsyncDataSyncWrapper(source, taskExecutor, logService);
    }

    /**
     * 获取并发控制扩展的包装类实例
     * 一般来讲都应该使用此包装类
     */
    public DataSyncService getSmartDataSyncWrapper(DataSyncService source) {
        return new SmartDataSyncWrapper(source, applicationContext, syncMissionCache, logService);
    }

    /**
     * 注册 SmartDataSyncWrapper 配套的数据同步任务完成的事件监听器
     */
    @Bean(name = "smartDataSyncApplicationListener")
    public ApplicationListener<SmartDataSyncWrapper.SmartEvent> smartDataSyncApplicationListener() {
        return new SmartDataSyncWrapper(syncMissionCache, logService);
    }
}
